package com.ruoyi.ai.domain;

import lombok.Data;

import java.util.List;
import java.util.Map;

/**
 * 消息参数请求体
 *
 * @author xudm
 * @date 2024年10月18日15:38:48
 */
@Data
public class MessageParamReqBody {
    private String model;
    private List<MessageParam> messages;
    //非必填参数

    /**
     * 响应内容是否流式返回
     */
    private boolean stream;
    /**
     * 流式响应的选项。仅当 stream: true 时可以设置 stream_options 参数。
     */
    private List<StreamOptionsParam> stream_options;

    /**
     * 模型回复最大长度（单位 token），取值范围为 [0, 4096]。
     * 输入 token 和输出 token 的总长度还受模型的上下文长度限制。
     */
    private Integer max_tokens;

    /**
     * 模型遇到 stop 字段所指定的字符串时将停止继续生成，这个词语本身不会输出。最多支持 4 个字符串。
     * <p>
     * ["你好", "天气"]
     */
    private List<String> stop;

    /**
     * 频率惩罚系数。如果值为正，会根据新 token 在文本中的出现频率对其进行惩罚，从而降低模型逐字重复的可能性。取值范围为 [-2.0, 2.0]。
     */
    private Float frequency_penalty;

    /**
     * 存在惩罚系数。如果值为正，会根据新 token 到目前为止是否出现在文本中对其进行惩罚，从而增加模型谈论新主题的可能性。取值范围为 [-2.0, 2.0]。
     */
    private Float presence_penalty;

    /**
     * 采样温度。控制了生成文本时对每个候选词的概率分布进行平滑的程度。取值范围为 [0, 1]。当取值为 0 时模型仅考虑对数概率最大的一个 token。
     * 较高的值（如 0.8）会使输出更加随机，而较低的值（如 0.2）会使输出更加集中确定。通常建议仅调整 temperature 或 top_p 其中之一，不建议两者都修改。x1
     */
    private Float temperature;

    /**
     * 核采样概率阈值。模型会考虑概率质量在 top_p 内的 token 结果。取值范围为 [0, 1]。当取值为 0 时模型仅考虑对数概率最大的一个 token。
     * 如 0.1 意味着只考虑概率质量最高的前 10% 的 token，取值越大生成的随机性越高，取值越低生成的确定性越高。通常建议仅调整 temperature 或 top_p 其中之一，不建议两者都修改。
     */
    private Float top_p;

    /**
     * 是否返回输出 tokens 的对数概率。
     * <p>
     * false：不返回对数概率信息
     * true：返回消息内容中每个输出 token 的对数概率
     */
    private Boolean logprobs;

    /**
     * 指定每个输出 token 位置最有可能返回的 token 数量，每个 token 都有关联的对数概率。仅当 logprobs: true 时可以设置 top_logprobs 参数，取值范围为 [0, 20]。
     */
    private Integer top_logprobs;

    /**
     * 调整指定 token 在模型输出内容中出现的概率，使模型生成的内容更加符合特定的偏好。logit_bias 字段接受一个 map 值，其中每个键为词表中的 token ID（使用 tokenization 接口获取），每个值为该 token 的偏差值，取值范围为 [-100, 100]。
     * -1 会减少选择的可能性，1 会增加选择的可能性；-100 会完全禁止选择该 token，100 会导致仅可选择该 token。该参数的实际效果可能因模型而异。
     * <p>
     * {
     * "1234": -100
     * }
     */
    private Map<String, Integer> logit_bias;

    /**
     * 模型可以调用的工具列表。目前，仅函数作为工具被支持。用这个来提供模型可能为其生成 JSON 输入的函数列表。
     */
    private List<ToolParam> tools;

    @Data
    public static class MessageParam {
        /**
         * 发出该消息的对话参与者角色，可选值包括：
         * <p>
         * system：System Message 系统消息
         * user：User Message 用户消息
         * assistant：Assistant Message 对话助手消息
         * tool：Tool Message 工具调用消息
         */
        private String role;

        /**
         * 消息内容
         * <p>
         * 当 role 为 system、user、tool时，参数必填
         * 当 role 为 assistant 时，content 与 tool_calls 参数二者至少填写其一
         */
        private String content;

        /**
         * 模型生成的工具调用。当 role 为 assistant 时，content 与 tool_calls 参数二者至少填其一
         */
        private List<MessageToolCallParam> tool_calls;

        /**
         * 此消息所回应的工具调用 ID，当 role 为 tool 时必填
         */
        private String tool_call_id;

    }

    @Data
    static class StreamOptionsParam {
        /**
         * 是否包含本次请求的 token 用量统计信息
         * <p>
         * false：不返回 token 用量信息
         * true：在 data: [DONE] 消息之前返回一个额外的块，此块上的 usage 字段代表整个请求的 token 用量，choices 字段为空数组。所有其他块也将包含 usage 字段，但值为 null。
         */
        private Boolean include_usage;
    }

    @Data
    static class ToolParam {
        private String type;
        private FunctionDefinition function;
    }

    @Data
    static class MessageToolCallParam {

        /**
         * 当前工具调用 ID
         */
        private String id;

        /**
         * 工具类型，
         * 当前仅支持function
         */
        private String type;

        /**
         * 模型需要调用的函数
         */
        private
        FunctionParam function;

    }

    @Data
    static class FunctionParam {
        /**
         * 模型需要调用的函数名称
         */
        private String name;
        /**
         * 模型生成的用于调用函数的参数，JSON 格式。
         * 请注意，模型并不总是生成有效的 JSON，并且可能会虚构出一些您的函数参数规范中未定义的参数。在调用函数之前，请在您的代码中验证这些参数是否有效。
         * {"location": "Boston, MA"}
         */
        private String arguments;
    }

    @Data
    static class FunctionDefinition {
        /**
         * 函数的名称 get_current_weather
         */
        private String name;
        /**
         * 对函数用途的描述，供模型判断何时以及如何调用该工具函数
         */
        private String description;
        /**
         * 函数请求参数，以 JSON Schema 格式描述。具体格式请参考 JSON Schema 文档
         * {
         * "type": "object",
         * "properties": {
         * "location": {
         * "type": "string",
         * "description": "城市，如：北京",
         * },
         * },
         * "required": ["location"],
         * }
         */
        private Object parameters;
    }
}
